package com.wangzhen.spring.bean.definition;

import com.wangzhen.spring.ioc.dependcy.entity.User;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;

import java.util.Objects;

/**
 * 演示基于BeanDefinition的附加属性操作
 * 备注：通过AttributeAccessor#setAttribute方法间接可以影响Bean的创建
 * @see org.springframework.core.AttributeAccessor
 *
 */
public class AttributeAccessorDemo {

    public static void main(String[] args) {
        //通过BeanDefinitionBuilder的方式来构建BeanDefinition
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);
        // 为User对象的BeanDefinition添加name属性
        beanDefinitionBuilder.addPropertyValue("name", "张三");
        // 获取BeanDefinition
        AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
        // 开始增加BeanDefinition的附加属性，附加属性的根源是BeanDefinition继承自AttributeAccessor
        beanDefinition.setAttribute("name", "张三plus");


        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // 注册BeanDefinition
        beanFactory.registerBeanDefinition("user", beanDefinition);
        // 为beanFactory添加后置的BeanPostProcessor
        beanFactory.addBeanPostProcessor(new BeanPostProcessor() {
            @Override
            public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
                return null;
            }
            // 在bean的初始化后阶段来判断User的BeanDefinition是否有额外的Attribute，如果有的话将此attribute设置的User的name属性中
            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                // 判断bean的名称是user，并且类型也是User
                if ("user".equals(beanName) && User.class == bean.getClass()) {
                    User user = User.class.cast(bean);
                    BeanDefinition definition = beanFactory.getBeanDefinition("user");
                    Object attr = definition.getAttribute("name");
                    if (attr != null) {
                        user.setName(Objects.toString(attr));
                    }
                }
                return null;
            }
        });

        System.out.println(beanFactory.getBean("user"));


    }
}
